/**
 * @param {string[]} words
 * @param {string} pattern
 * @return {string[]}
 */
var WordMapper = function() {
    this.store = {};
    this.valueSet = new Set();
};

WordMapper.prototype.hasKey = function(s) {
    return this.store[s] != null;
};

WordMapper.prototype.hasValue = function(v) {
    return this.valueSet.has(v);
}

WordMapper.prototype.get = function(s) {
    if (this.hasKey(s)) {
        return this.store[s];
    }
    
    throw new Error('Key not found: ', s);
};

WordMapper.prototype.put = function(s, v) {
    if (this.hasKey(s)) {
        throw new Error('Cannot overwrite key: ', s);
    }
    else if (this.hasValue(v)) {
        throw new Error('Cannot duplicate value: ', v);
    }

    this.store[s] = v;
    this.valueSet.add(v);
};

var findAndReplacePattern = function(words, pattern) {
    return words.filter(w => checkWord(w, pattern));
};

var checkWord = function(word, pattern) {
    var wordMapper = new WordMapper();

    for (var i = 0; i < word.length; i++) {
        var c1 = word[i];
        var c2 = pattern[i];

        if (wordMapper.hasKey(c1)) {
            if (wordMapper.get(c1) !== c2) {
                return false;
            }
        }
        else if (wordMapper.hasValue(c2)) {
            return false;
        }
        else {
            wordMapper.put(c1, c2);
        }
    }

    return true;
};

